package com.chenfan.filestore.service.biz.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chenfan.ccp.common.exception.ApiException;
import com.chenfan.ccp.util.tool.UuidUtil;
import com.chenfan.filestore.config.FileStoreConfig;
import com.chenfan.filestore.dto.BatchImportTemplateDTO;
import com.chenfan.filestore.dto.BatchImportTemplateQueryDTO;
import com.chenfan.filestore.exception.FileStoreCode;
import com.chenfan.filestore.model.BatchImportTemplate;
import com.chenfan.filestore.service.BatchImportTemplateService;
import com.chenfan.filestore.service.FileService;
import com.chenfan.filestore.service.biz.BatchImportTemplateBiz;
import com.chenfan.filestore.utils.FileUtil;
import com.chenfan.filestore.vo.BatchImportTemplateVO;
import com.chenfan.filestore.vo.FileResult;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author K
 * @date 2023/5/15 2:30 PM
 */
@Service
public class BatchImportTemplateBizImpl implements BatchImportTemplateBiz {

    @Autowired
    private FileService fileService;
    @Autowired
    private FileStoreConfig fileStoreConfig;

    @Autowired
    private BatchImportTemplateService batchImportTemplateService;

    @Override
    public Long createBatchImportTemplate(BatchImportTemplateDTO batchImportTemplateDTO) throws Exception {
        BatchImportTemplate checkTemplate = batchImportTemplateService.findByTemplateCode(batchImportTemplateDTO.getTemplateCode());
        if (Objects.nonNull(checkTemplate)) {
            throw new ApiException(FileStoreCode.TEMPLATE_CODE_EXISTS);
        }

        BatchImportTemplate batchImportTemplate = BatchImportTemplate.ofDefault(batchImportTemplateDTO);
        // 解析excel, 去除除表头之外的数据
        String downloadUrl = parseExcelAndUpload(batchImportTemplate);
        Long templateId = UuidUtil.generateId();
        batchImportTemplate.setTemplateId(templateId);
        batchImportTemplate.setTemplateDownloadUrl(downloadUrl);
        batchImportTemplateService.save(batchImportTemplate);
        return templateId;
    }

    @Override
    public void updateBatchImportTemplate(BatchImportTemplateDTO batchImportTemplateDTO) throws Exception {
        BatchImportTemplate check = getAndCheck(batchImportTemplateDTO.getTemplateId());
        BatchImportTemplate batchImportTemplate = BatchImportTemplate.ofDefault(batchImportTemplateDTO);
        batchImportTemplate.setTemplateId(batchImportTemplateDTO.getTemplateId());
        batchImportTemplate.updateSelf();
        if (!batchImportTemplate.getTemplateUrl().equals(check.getTemplateUrl())) {
            String downloadUrl = parseExcelAndUpload(batchImportTemplate);
            batchImportTemplate.setTemplateDownloadUrl(downloadUrl);
        }
        batchImportTemplateService.updateById(batchImportTemplate);
    }

    @Override
    public Page<BatchImportTemplateVO> pageBatchImportTemplate(BatchImportTemplateQueryDTO query) {
        Page<BatchImportTemplateVO> batchImportTemplateVOPage = new Page<>(query.getPageSize(), query.getPageNum());
        Page<BatchImportTemplate> batchImportTemplatePage = batchImportTemplateService.pageBatchImportTemplate(query);

        List<BatchImportTemplateVO> records = batchImportTemplatePage.getRecords().stream().map(e -> {
            BatchImportTemplateVO batchImportTemplateVO = new BatchImportTemplateVO();
            BeanUtils.copyProperties(e, batchImportTemplateVO);
            return batchImportTemplateVO;
        }).collect(Collectors.toList());

        batchImportTemplateVOPage.setRecords(records);
        batchImportTemplateVOPage.setTotal(batchImportTemplatePage.getTotal());
        batchImportTemplateVOPage.setCurrent(batchImportTemplatePage.getCurrent());
        return batchImportTemplateVOPage;
    }

    @Override
    public void switchStatus(Long templateId, Integer status) {
        BatchImportTemplate batchImportTemplate = getAndCheck(templateId);
        if ((batchImportTemplate.getStatus() ^ status) == 0) {
            throw new ApiException(FileStoreCode.STATUS_NOT_CHANGE);
        }
        batchImportTemplate.setStatus(status);
        batchImportTemplate.updateSelf();

        batchImportTemplateService.updateById(batchImportTemplate);
    }

    @Override
    public BatchImportTemplateVO getBatchImportTemplateById(Long templateId) {
        BatchImportTemplateVO batchImportTemplateVO = new BatchImportTemplateVO();

        BatchImportTemplate template = getAndCheck(templateId);
        BeanUtils.copyProperties(template, batchImportTemplateVO);
        return batchImportTemplateVO;
    }

    @Override
    public BatchImportTemplateVO getBatchImportTemplate(String templateCode) {
        BatchImportTemplate template = batchImportTemplateService.findByTemplateCode(templateCode);
        if (Objects.isNull(template)) {
            throw new ApiException(FileStoreCode.TEMPLATE_DOES_NOT_EXISTS);
        }
        BatchImportTemplateVO batchImportTemplateVO = new BatchImportTemplateVO();
        BeanUtils.copyProperties(template, batchImportTemplateVO);
        return batchImportTemplateVO;
    }

    private BatchImportTemplate getAndCheck(Long templateId) {
        BatchImportTemplate template = batchImportTemplateService.getById(templateId);
        if (Objects.isNull(template)) {
            throw new ApiException(FileStoreCode.TEMPLATE_DOES_NOT_EXISTS);
        }
        return template;
    }

    public String parseExcelAndUpload(BatchImportTemplate batchImportTemplate) throws Exception {
        // 1. 读取文件.
        /**
         * 写入文件配置
         */
        String localParentDir = new StringBuffer(fileStoreConfig.getTempPath()).append(FileUtil.getUploadDir()).toString();
        String newLocalFilePath = new StringBuffer(localParentDir).append(FileUtil.uuid()+".").append(FileUtil.suffix(batchImportTemplate.getTemplateUrl())).toString();
        FileUtil.createParentDir(localParentDir);
        ExcelWriter excelWriter = EasyExcel
                .write(new FileOutputStream(newLocalFilePath))
                .excelType(ExcelTypeEnum.XLSX)
                .autoCloseStream(true).build();
        WriteSheet writeSheet = EasyExcel.writerSheet(0,"sheet0").build();
        InputStream inputStream = fileService.getInputStream(batchImportTemplate.getTemplateUrl());
        EasyExcel.read(inputStream, new ReadListener<HashMap<String, String>>() {
            @Override
            public void onException(Exception exception, AnalysisContext context) {
                System.out.println(exception.getMessage());
            }

            @Override
            public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
                List<List<String>> header = headMap.values().stream().map(value -> Collections.singletonList(value.getStringValue())).collect(Collectors.toList());
                writeSheet.setHead(header);
            }

            @Override
            public void invoke(HashMap<String, String> data, AnalysisContext context) {
            }

            @Override
            public void extra(CellExtra extra, AnalysisContext context) {

            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {

            }

            @Override
            public boolean hasNext(AnalysisContext context) {
                return false;
            }
        }).sheet().doRead();

        excelWriter.write(Collections.emptyList(), writeSheet);
        excelWriter.finish();

        FileResult fileResult = fileService.uploadFile(new File(newLocalFilePath));
        return fileResult.getId();
    }
}
